home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
C
/
LIB
/
UNIXLIB37B
/
!UnixLib37
/
src
/
unix
/
c
/
stat
< prev
next >
Wrap
Text File
|
1996-11-09
|
5KB
|
214 lines
/****************************************************************************
*
* $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/stat,v $
* $Date: 1996/10/30 22:04:51 $
* $Revision: 1.5 $
* $State: Rel $
* $Author: unixlib $
*
* $Log: stat,v $
* Revision 1.5 1996/10/30 22:04:51 unixlib
* Massive changes made by Nick Burret and Peter Burwood.
*
* Revision 1.4 1996/09/16 21:23:52 unixlib
* CL_0002 Nick Burret
* Minor changes to file handling
* Change most error numbers, and use in assembler sources (SJC)
* Various minor bug fixes and compatability changes.
*
* Revision 1.3 1996/07/21 22:12:31 unixlib
* CL_0001 Nick Burret
* Improve memory handling. Remove C++ library incompatibilities.
* Improve file stat routines.
*
* Revision 1.2 1996/05/06 09:01:35 unixlib
* Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
* Saved for 3.7a release.
*
* Revision 1.1 1996/04/19 21:35:27 simon
* Initial revision
*
***************************************************************************/
static const char rcs_id[] = "$Id: stat,v 1.5 1996/10/30 22:04:51 unixlib Rel $";
#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/dev.h>
#include <sys/unix.h>
#include <sys/stat.h>
#include <sys/os.h>
#include <sys/swis.h>
static void __stat (register int *, register struct stat *);
int
stat (const char *fname, struct stat *buf)
{
int r[6];
_kernel_oserror *e;
char *file;
if (!buf)
{
errno = EINVAL;
return (-1);
}
file = __uname ((char *)fname, 0);
if (e = os_file (0x05, file, r))
{
__seterr (e);
return (-1);
}
if (!r[0])
{
errno = ENOENT;
return (-1);
}
buf->st_dev = makedev (DEV_RISCOS, 0);
__stat (r, buf);
return (0);
}
int
lstat (const char *fname, struct stat *buf)
{
return stat (fname, buf);
}
int
fstat (int fd, struct stat *buf)
{
register struct file *f;
if (!buf)
{
errno = EINVAL;
return (-1);
}
if (BADF (fd))
{
errno = EBADF;
return (-1);
}
f = __u->file + fd;
buf->st_dev = f->dev;
__stat (f->r, buf);
return (0);
}
/* This function is used by __stat() and readdir(). */
unsigned int
__get_file_serial_no (char *fname)
{
int r[10];
char tmp[256], *s;
unsigned int ino;
char *name;
/* The file serial number, which distringuishes this file from
all other files on the same device.
Hash the filename to hopefully make a fairly unique number. */
name = __uname (fname, 0);
r[0] = 37;
r[1] = (int)name;
r[2] = (int)tmp;
r[3] = r[4] = 0;
r[5] = 255;
ino = r[3] + r[4];
if (!os_swi (OS_FSControl, r) && r[5] >= 0)
{
for (s = tmp; s[0] || s[1]; s += 2)
ino += (s[1] == 0) ? s[0]<<5 : s[0] * s[1];
}
return ino;
}
static void
__stat (register int *r, register struct stat *buf)
{
buf->st_ino = __get_file_serial_no ((char *)r[1]);
buf->st_mode = ((r[5] & 0001) << 8) | ((r[5] & 0002) << 6) |
((r[5] & 0020) >> 2) | ((r[5] & 0040) >> 4);
switch (r[0])
{
case 1:
buf->st_mode |= S_IFREG;
break;
case 2: /* Normal directory */
buf->st_mode |= S_IFDIR | 0700; /* FS bug */
break;
case 3: /* Image directory (RISC OS 3 and above) */
buf->st_mode |= S_IFDIR | ((buf->st_mode & 0400) >> 2); /* FS bug */
break;
}
switch (major (buf->st_dev))
{
case DEV_TTY:
buf->st_mode |= S_IFCHR;
break;
case DEV_PIPE:
buf->st_mode |= 0;
break;
}
/* The number of hard links to the file. For RISC OS, there is only
one hard link since only one directory can point to the file.
Symbolic links are not counted in the total. */
buf->st_nlink = 1;
buf->st_uid = 1;
buf->st_gid = 1;
buf->st_rdev = 0;
buf->st_size = r[4];
/* Disc space that the file occupies, measured in units of 512
byte blocks. */
buf->st_nblocks = r[4] / 512;
/* Optimal block size for reading or writing this file, in bytes.
Since sector sizes are usually 512 or 1024 bytes on RISC OS
disc formats, we'll safely assume a block size of 1024. */
buf->st_blksize = 1024;
if ((((unsigned int) r[2]) >> 20) == 0xfff) /* date stamped file */
{
register unsigned int t1, t2, tc;
t1 = (unsigned int) (r[3]);
t2 = (unsigned int) (r[2] & 0xff);
tc = 0x6e996a00U;
if (t1 < tc)
t2--;
t1 -= tc;
t2 -= 0x33; /* 00:00:00 Jan. 1 1970 = 0x336e996a00 */
t1 = (t1 / 100) + (t2 * 42949673U); /* 0x100000000 / 100 = 42949672.96 */
t1 -= (t2 / 25); /* compensate for .04 error */
buf->st_atime = buf->st_mtime = buf->st_ctime = t1;
}
else
buf->st_atime = buf->st_mtime = buf->st_ctime = 0;
}